---
title: "Roll your own linux password manager w/ gpg and openssl"
date:  2019-01-16
category:  TechTips
---

Managing your passwords is important, and can be difficult to do well.  This
post details how you can quickly and easily write a personal password manager
to use strong, unique passwords on all the many sites and services you may use
online.

First, a bit of context about why I think a system like this is important.  The
primary reason to use a password manager, in my opinion, is because of the
regularity and severity of data breaches; see
[here](https://www.businessinsider.com/data-breaches-2018-4?op=1) and
[here](https://digitalguardian.com/blog/history-data-breaches) for stories about
the growing prevalence of this problem.

We provide websites and web services, often many, many different sites and
services, with large amounts of data and personal information, and sometimes the
entities/companies holding that information lose control of it.  They get
hacked, or there is a bad actor within the company, or something else happens
that that information gets leaked.  For some services, especially those with
a lot of personal information in their databases, a single breach can be very
damaging to a person.

But the kicker is that if you reuse the same password on multiple sites, you
risk letting that single data breach be much, much more damaging than it has to
be.  Once a malicious actor has your password for your email account, they are
likely to try the same password, and variants of it, to log into whatever other
accounts they can tie to you: social media accounts, banking accounts, web
forums, university services, professional or corporate web portals, healthcare
websites, etc.  This is called [credential
stuffing](https://en.wikipedia.org/wiki/Credential_stuffing).  Because of this risk,
password re-use is bad practice, and you should avoid it if you can.

One last note: some people use "unique" passwords for different sites, but use
a common stem with a unique tail.  For example, say you are signed up to
3 different web services, you may create passwords that look like this:

- applesauce!email
- applesauce!importantBankAccount
- applesauce!coolSocialMediaSite

This will offer a little more protection than having identical passwords for
each site (the password [hashes](https://en.wikipedia.org/wiki/Cryptographic_hash_function) won't be the same, and an attacker may
have difficulty guessing the tail of the passwords for other sites), but it is
not as secure as having unrelated, unique passwords.  Fortunately, with the
system below, we'll see how easy it is to create such passwords.

So if I've convinced you of the value of password management, or if you came
here so convinced already, read on!

<h2>Password Manager Details</h2>

The following password management system will not work for everyone.  It is
specifically tailored to someone who uses a single device (i.e., a laptop) for
almost all of their computing, who runs GNU/Linux, and who spends a lot of time
within a shell/terminal emulator.  This is, of course, a fairly small niche.
The ideas can be adapted to other setups (e.g., laptop + desktop + smartphone),
but you will have to do some more legwork to get it working.  If you'd like some
help doing so, feel free to email me.

There are three parts to the password manager:

1. an encrypted password file
2. a shell script to decrypt and read the passwords
3. and a shell alias, to easily run the shell script

Let's break down each part.

<h3>Step 1 - Encrypted password file</h3>

First we create a plain text file with our passwords in it.  We will assume, for
the sake of this tutorial, that the file will be called password_file, but
I would encourage you to use something a little less likely to draw unwanted
attention, in the unfortunate event that someone gets hold of your machine that
you'd rather hadn't.

Open up your text editor of choice, and enter your passwords, one per line, in
the following format:

*service:password*

The name of the service can be whatever you like; it's what you will use to
query the password file later, so don't make it too long.

Enter all the passwords you'd like to manage.  At the end of this step, you
should have a file that looks like this:

*webService1:coolpassword1*  
*fastmail:coolpassword2*  
*uniMail:awesomepassword*  
*socialMediaSite:lamepassword*  

At this point, you have two choices: you can encrypt this file, and move on to
writing the shell script and the shell alias that will allow you to decrypt and
query the file.  Or you can generate new, strong passwords for each of the
services listed, and go change those passwords through the services' respective
interfaces (e.g., login, go to account/preferences/settings, and choose change
password).  I would strongly encourage you to do this.  Maybe not right away;
you could change the passwords for the various services incrementally, over
time, and achieve the same effect.  Changing your existing passwords to stronger
ones will likely be the most time consuming portion of this process, but it's
also the most valuable.

To generate a password, simply open a terminal and run this command:

`$ openssl rand -base64 24`

Caveat: sometimes this command will generate a password with a character in it
that won't be accepted by the website/service for which you're trying to change
your password.  In that case, just generate another one.  They are cheap to
create, after all.

This command will generate a psuedo-random, 24 character password (you can use
whatever length you'd like).  It will not be the sort of password that you can
easily memorize, but your encrypted file will have no trouble with it.  These
passwords will be much harder to crack than most of the passwords people
generate out of their own head.  And a fringe benefit of using these passwords
is that you can clear the space in your brain memory that was previously
allocated to password storage of all these sites, and put more interesting data
in it, such as [the names of all the world's national capitals]
(https://en.wikipedia.org/wiki/List_of_national_capitals_in_alphabetical_order).

Once you've got your password file in place, hopefully with a bunch of new,
strong, gibberish-looking passwords, we move on to encrypting the file.

To encrypt the text file, quit your text editor, open a shell/terminal, and type
the following command:

`$ gpg -c password_file`

or, if you are not in the same directory as the password file, you can type:

`$ gpg -c /path/to/password_file`

GPG will then prompt you for a password, which will be used to perform
[symmetric-key
encryption](https://en.wikipedia.org/wiki/Symmetric-key_algorithm).  This
password you *will* have to remember, because you will be typing it in whenever
you query your encrypted file for a website password.  Make sure to choose
a strong password, but one that you can remember (or write it down on a piece of
paper while you're learning it).  I recommend rotating this encryption password
regularly.

You should now have an encrypted password file, called password_file.gpg.  You
can decrypt the file with the following command:

`$ gpg -d password_file.gpg > password_file`

GPG will prompt you for your encryption key/password, and upon entering it you
will again have the plaintext file.  Whenever you need to add a new
website/service to this file,  you will decrypt the file, add a new line,
re-encrypt it, and finally delete the plaintext version.  You will follow the
same procedure if you change the password for an existing service.

<h3>Step 2 - Shell script</h3>

Now that your password file is setup, filled with strong passwords, and
encrypted, we need a way to query it.  We can do that with a simple shell script
that uses gpg, grep, cut, tr, and xclip.  All but xclip are usually installed by
default on GNU/Linux distros, and all are readily available in the repos for
most any distro.  You should have no trouble tracking down these utilities.

The logic of the shell script is very simple:

1. Decrypt the password file
2. Search the password file for the site name provided
3. Parse the line from step 2 and extract only the password
4. Place the password into the X clipboard
5. Remove the decrypted file from disk
6. Remove the password from gpg's memory cache (optional)

The entire script file looks like this:

    #!/bin/sh

    gpg -d /path/to/password_file.gpg > /path/to/decrypted/password_file
    grep  $1 /path/to/decrypted/password_file | cut -d ":" -f 2 | tr -d '\n' | xclip
    rm /path/to/decrypted/password_file
    echo RELOADAGENT | gpg-connect-agent

This will look for the colon after the service name you feed into it (via the
shell alias, up next), cut the line there, and return just the password.  It
then feeds that result into xclip, which simply puts the text into your
X clipboard.  You can then middle-click or shift-insert to paste the text into,
e.g., a browser login window, and the password text never needs to be visible on
screen, and therefore remains safe from visual capture via, e.g., [shoulder
surfing](https://en.wikipedia.org/wiki/Shoulder_surfing_%28computer_security%29).

You can call this script file anything you like.  I call mine pman.sh, in
keeping with the Unix tradition of very short program names.  You will use the
filename in your shell alias definition below.

<h3>Step 3 - Shell alias</h3>

Finally, you can make use of this shell script easier by defining a shell alias
in your .bashrc or .zshrc (or whatever other shell you may be using).

The alias definition that I use, for use with [zsh](https://www.zsh.org), but
which should work the same in .bashrc, is the following:

`$ alias pw="/path/to/pman.sh "`

Note the space after the file name/extension.  This is important, otherwise the
filename will run-on to the argument.

This line defines the alias **pw**.  So to grab my email password, I type 

`$ pw email`

get prompted by gpg for my password (i.e., encryption key), and that's
it.  My password is now sitting in the X clipboard, ready to be pasted into
either a terminal (I use this all the time with the mail user agent (MUA)
program that I use, called [neomutt](https://www.neomutt.org)) or a browser
window.

Put the alias line into your shell's rc file, and then source the file, e.g.,

`$ source ~/.zshrc`

or open a new terminal, and try out your new tool.  You should now have
a fully-functioning (if alpha-level) password manager!

<h3>Recap</h3>

In overview and summary, the steps to build your own password manager are:

1. Create a text file with the names of the sites you want to manage
2. Generate strong unique passwords for each site using openssl
3. Encrypt the password file using gpg
4. Write a shell script to decrypt and query the encrypted file
5. Write an alias to make running the shell script easy

<h3>Conclusion</h3>

Hopefully this tutorial will help some privacy and security enthusiasts and/or
some GNU/Linux and free software supporters manage their passwords a bit more
securely and comfortably.  If you have any feedback, suggestions, or questions,
feel free to email me.

As a final note, if you use multiple devices, or for some other reason don't
want to use the system I've detailed here, I encourage you to look into some of
the commercial password managers out there that do this sort of thing.  These
tend to install as browser add-ons/plugins, rather than being run through the
terminal or via a desktop app. Some of the best on the market include
[LastPass](https://www.lastpass.com) and
[1Pass](https://agilebits.com/onepassword).  Commercial password managers are
even easier to use than the system I've described here, and they will provide an
important layer of security to your online activities.

Happy surfing!


